package repository

import (
	"context"
	"errors"

	"gorm.io/gorm"

	"BookStack/internal/domain/book"
)

// chapterRepository 章节仓储实现
type chapterRepository struct {
	db *gorm.DB
}

// NewChapterRepository 创建章节仓储
func NewChapterRepository(db *gorm.DB) book.ChapterRepository {
	return &chapterRepository{
		db: db,
	}
}

// Create 创建章节
func (r *chapterRepository) Create(ctx context.Context, c *book.Chapter) error {
	return r.db.WithContext(ctx).Create(c).Error
}

// GetByID 通过ID获取章节
func (r *chapterRepository) GetByID(ctx context.Context, id uint) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).First(&c, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// GetByBookIDAndSlug 通过书籍ID和章节标识获取章节
func (r *chapterRepository) GetByBookIDAndSlug(ctx context.Context, bookID uint, slug string) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).Where("book_id = ? AND slug = ?", bookID, slug).First(&c).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// GetByBookIDAndOrder 通过书籍ID和章节顺序获取章节
func (r *chapterRepository) GetByBookIDAndOrder(ctx context.Context, bookID uint, order int) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).Where("book_id = ? AND `order` = ?", bookID, order).First(&c).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// Update 更新章节
func (r *chapterRepository) Update(ctx context.Context, c *book.Chapter) error {
	return r.db.WithContext(ctx).Save(c).Error
}

// Delete 删除章节
func (r *chapterRepository) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Delete(&book.Chapter{}, id).Error
}

// ListByBookID 获取书籍的章节列表
func (r *chapterRepository) ListByBookID(ctx context.Context, bookID uint, offset, limit int) ([]*book.Chapter, int64, error) {
	var chapters []*book.Chapter
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Chapter{}).
		Where("book_id = ? AND deleted_at IS NULL", bookID)

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("`order` ASC").Find(&chapters).Error; err != nil {
		return nil, 0, err
	}

	return chapters, total, nil
}

// GetPrevChapter 获取上一个章节
func (r *chapterRepository) GetPrevChapter(ctx context.Context, bookID uint, currentOrder int) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).
		Where("book_id = ? AND `order` < ? AND deleted_at IS NULL", bookID, currentOrder).
		Order("`order` DESC").
		First(&c).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// GetNextChapter 获取下一个章节
func (r *chapterRepository) GetNextChapter(ctx context.Context, bookID uint, currentOrder int) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).
		Where("book_id = ? AND `order` > ? AND deleted_at IS NULL", bookID, currentOrder).
		Order("`order` ASC").
		First(&c).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// SearchInBook 在书籍中搜索章节
func (r *chapterRepository) SearchInBook(ctx context.Context, bookID uint, keyword string, offset, limit int) ([]*book.Chapter, int64, error) {
	var chapters []*book.Chapter
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Chapter{}).
		Where("book_id = ? AND deleted_at IS NULL", bookID).
		Where("title LIKE ? OR content LIKE ?", "%"+keyword+"%", "%"+keyword+"%")

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("`order` ASC").Find(&chapters).Error; err != nil {
		return nil, 0, err
	}

	return chapters, total, nil
}

// GetMaxOrderByBookID 获取书籍中最大的章节顺序
func (r *chapterRepository) GetMaxOrderByBookID(ctx context.Context, bookID uint) (int, error) {
	var maxOrder int
	if err := r.db.WithContext(ctx).Model(&book.Chapter{}).
		Where("book_id = ? AND deleted_at IS NULL", bookID).
		Select("COALESCE(MAX(`order`), 0)").
		Scan(&maxOrder).Error; err != nil {
		return 0, err
	}
	return maxOrder, nil
}

// ReorderChapters 重新排序章节
func (r *chapterRepository) ReorderChapters(ctx context.Context, bookID uint, orderMap map[uint]int) error {
	tx := r.db.WithContext(ctx).Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	for chapterID, order := range orderMap {
		if err := tx.Model(&book.Chapter{}).
			Where("id = ? AND book_id = ?", chapterID, bookID).
			Update("order", order).Error; err != nil {
			tx.Rollback()
			return err
		}
	}

	return tx.Commit().Error
}

// ListSoftDeleted 获取书籍中已软删除的章节列表
func (r *chapterRepository) ListSoftDeleted(ctx context.Context, bookID uint, offset, limit int) ([]*book.Chapter, int64, error) {
	var chapters []*book.Chapter
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Chapter{}).Unscoped().
		Where("book_id = ? AND deleted_at IS NOT NULL", bookID)

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("deleted_at DESC").Find(&chapters).Error; err != nil {
		return nil, 0, err
	}

	return chapters, total, nil
}

// GetSoftDeletedByID 通过ID获取已软删除的章节
func (r *chapterRepository) GetSoftDeletedByID(ctx context.Context, id uint) (*book.Chapter, error) {
	var c book.Chapter
	if err := r.db.WithContext(ctx).Unscoped().
		Where("id = ? AND deleted_at IS NOT NULL", id).
		First(&c).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &c, nil
}

// Restore 恢复已软删除的章节
func (r *chapterRepository) Restore(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Unscoped().Model(&book.Chapter{}).
		Where("id = ?", id).
		Update("deleted_at", nil).Error
}

// HardDelete 硬删除章节
func (r *chapterRepository) HardDelete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Unscoped().Delete(&book.Chapter{}, id).Error
}

// BatchCreate 批量创建章节
func (r *chapterRepository) BatchCreate(ctx context.Context, chapters []*book.Chapter) error {
	return r.db.WithContext(ctx).Create(chapters).Error
}

// BatchDelete 批量删除章节
func (r *chapterRepository) BatchDelete(ctx context.Context, ids []uint) error {
	return r.db.WithContext(ctx).Where("id IN ?", ids).Delete(&book.Chapter{}).Error
}
